import { useActiveTab } from "@renderer/hooks/use-active-tab";
import { useActiveThread } from "@renderer/hooks/use-active-thread";
import { useMessagesByThreadConditional } from "@renderer/queries/hooks/use-messages";
import { useEnabledModelWithProvider } from "@renderer/queries/hooks/use-models";
import {
  usePrivacySetting,
  useSelectedModelId,
} from "@renderer/queries/hooks/use-settings";
import { EventNames, emitter } from "@renderer/services/event-service";
import logger from "@shared/logger/renderer-logger";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

const { tabService, threadService, settingsService } = window.service;

export interface PrivacyModeState {
  isPrivate: boolean;
  canToggle: boolean;
}

export function usePrivacyMode() {
  const { t } = useTranslation();
  const { activeTab, setActiveTabId } = useActiveTab();
  const { selectedThread, setActiveThreadId } = useActiveThread();

  const { data: selectedModelId } = useSelectedModelId();
  const { data: isPrivateSetting } = usePrivacySetting();

  const { data: provider } = useEnabledModelWithProvider(selectedModelId || "");

  const { data: messages, isFetching: fetching } =
    useMessagesByThreadConditional(activeTab?.threadId);

  const [privacyState, setPrivacyState] = useState<PrivacyModeState>({
    isPrivate: false,
    canToggle: false,
  });

  const isSessionStarted = messages && messages.length > 0;
  const isThreadTab = activeTab?.type === "thread";

  useEffect(() => {
    if (activeTab?.threadId) {
      setPrivacyState((prev) => ({
        ...prev,
        canToggle: false,
      }));
    } else if (activeTab?.id) {
      setPrivacyState((prev) => ({
        ...prev,
        canToggle: true,
      }));
    }
  }, [activeTab?.threadId, activeTab?.id]);

  const updatePrivacyState = useCallback(() => {
    if (!fetching) {
      const canToggle = activeTab
        ? isThreadTab
          ? !isSessionStarted
          : false
        : true;

      let isPrivate = false;
      if (activeTab?.id) {
        isPrivate = activeTab.isPrivate || false;
      } else {
        isPrivate = isPrivateSetting || false;
      }

      setPrivacyState({
        isPrivate,
        canToggle,
      });
    }
  }, [fetching, isSessionStarted, activeTab, isPrivateSetting, isThreadTab]);

  useEffect(() => {
    updatePrivacyState();
  }, [updatePrivacyState]);

  const togglePrivacyMode = useCallback(
    async (targetTabId?: string) => {
      // If a specific tabId is provided, we're operating on that tab
      const targetTab = targetTabId
        ? await tabService.getTab(targetTabId)
        : activeTab;

      const currentPrivacyState = targetTabId
        ? targetTab?.isPrivate || false
        : privacyState.isPrivate;

      // For non-active tabs, we don't check canToggle
      if (!targetTabId && !privacyState.canToggle) {
        return false;
      }

      try {
        const newPrivacyState = !currentPrivacyState;

        // Only update local state if we're toggling the active tab
        if (!targetTabId) {
          setPrivacyState((prev) => {
            return {
              ...prev,
              isPrivate: newPrivacyState,
            };
          });
        }

        if (targetTab?.id) {
          await tabService.updateTab(targetTab.id, {
            isPrivate: newPrivacyState,
          });

          // If this tab has a thread, update the thread's privacy state too
          if (targetTab.threadId) {
            await threadService.updateThreadPrivate(
              targetTab.threadId,
              newPrivacyState,
            );
          }
        } else if (!targetTabId) {
          // Only set global setting if we're not targeting a specific tab
          await settingsService.setEnablePrivate(newPrivacyState);

          if (selectedThread?.id) {
            await threadService.updateThreadPrivate(
              selectedThread.id,
              newPrivacyState,
            );
          }
        }

        emitter.emit(EventNames.PRIVACY_MODE_TOGGLE, {
          isPrivate: newPrivacyState,
          tabId: targetTab?.id,
          threadId: targetTab?.threadId || selectedThread?.id,
        });

        toast.success(
          newPrivacyState
            ? t("privacy-mode.enabled.description")
            : t("privacy-mode.disabled.description"),
        );

        return true;
      } catch (error) {
        logger.error("Failed to toggle privacy mode", { error });
        // Rollback local state on error (only for active tab)
        if (!targetTabId) {
          setPrivacyState((prev) => ({
            ...prev,
            isPrivate: !prev.isPrivate,
          }));
        }
        toast.error(t("privacy-mode.error.description"));
        return false;
      }
    },
    [
      privacyState.canToggle,
      privacyState.isPrivate,
      activeTab,
      selectedThread?.id,
      t,
    ],
  );

  const confirmSwitchFromPrivate = useCallback(
    async (action: string): Promise<boolean> => {
      if (!privacyState.isPrivate) {
        return true;
      }

      return new Promise((resolve) => {
        const handleConfirm = () => {
          resolve(true);
          cleanup();
        };

        const handleCancel = () => {
          resolve(false);
          cleanup();
        };

        const cleanup = () => {
          emitter.off(EventNames.PRIVACY_MODE_CONFIRM, handleConfirm);
          emitter.off(EventNames.PRIVACY_MODE_CANCEL, handleCancel);
        };

        emitter.on(EventNames.PRIVACY_MODE_CONFIRM, handleConfirm);
        emitter.on(EventNames.PRIVACY_MODE_CANCEL, handleCancel);

        emitter.emit(EventNames.PRIVACY_MODE_CONFIRM_DIALOG, {
          action,
          message: t("privacy-mode.confirm-switch.message", { action }),
        });
      });
    },
    [privacyState.isPrivate, t],
  );

  const createPrivateSession = useCallback(async () => {
    try {
      const newThread = await threadService.createNewThread({
        title: t("thread.private-thread-title"),
        providerId: provider?.provider?.id || "",
        modelId: selectedModelId || "",
        isPrivate: true,
      });

      const newTab = await tabService.insertTab({
        title: t("thread.private-thread-title"),
        type: "thread",
        isPrivate: true,
        threadId: newThread.id,
        inputValue: null,
        files: null,
        path: "/",
      });

      await setActiveTabId(newTab.id);
      await setActiveThreadId(newThread.id);

      return { thread: newThread, tab: newTab };
    } catch (error) {
      logger.error("Failed to create private session", { error });
      throw error;
    }
  }, [t, setActiveTabId, setActiveThreadId, selectedModelId, provider]);

  const inheritPrivacyState = useCallback(async () => {
    if (!privacyState.isPrivate) {
      return false;
    }

    try {
      await createPrivateSession();
      return true;
    } catch (error) {
      logger.error("Failed to inherit privacy state", { error });
      return false;
    }
  }, [privacyState.isPrivate, createPrivateSession]);

  // Cleanup private session data
  const cleanupPrivateSession = useCallback(async () => {
    if (!privacyState.isPrivate) {
      return;
    }

    try {
      if (selectedThread?.id && selectedThread.isPrivate) {
        await threadService.deleteThread(selectedThread.id);
      }

      if (activeTab?.id && activeTab.isPrivate) {
        await tabService.deleteTab(activeTab.id);
      }
    } catch (error) {
      logger.error("Failed to cleanup private session", { error });
    }
  }, [
    privacyState.isPrivate,
    selectedThread?.id,
    selectedThread?.isPrivate,
    activeTab?.id,
    activeTab?.isPrivate,
  ]);

  return {
    privacyState,
    togglePrivacyMode,
    confirmSwitchFromPrivate,
    createPrivateSession,
    inheritPrivacyState,
    cleanupPrivateSession,
    updatePrivacyState,
  };
}
